package services

import (
	"errors"
	"rego-top/database"
	"rego-top/dto"
	"rego-top/models"
	"rego-top/utils"
	"time"

	"gorm.io/gorm"
)

type UserService struct{}

func NewUserService() *UserService {
	return &UserService{}
}


func (s *UserService) GetUserByID(userID uint) (*models.User, error) {
	var user models.User
	if err := database.DB.Where("id = ?", userID).First(&user).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New("用户不存在")
		}
		return nil, errors.New("查询用户失败")
	}
	return &user, nil
}

// Register 用户注册
func (s *UserService) Register(req dto.RegisterRequest) (*models.User, error) {
	// 检查用户名是否已存在
	var existingUser models.User
	if err := database.DB.Where("username = ? OR email = ?", req.Username, req.Email).First(&existingUser).Error; err == nil {
		if existingUser.Username == req.Username {
			return nil, errors.New("用户名已存在")
		}
		if existingUser.Email == req.Email {
			return nil, errors.New("邮箱已存在")
		}
	}

	// 加密密码
	hashedPassword, err := utils.HashPassword(req.Password)
	if err != nil {
		return nil, errors.New("密码加密失败")
	}

	// 生成邮箱验证令牌
	emailToken, err := utils.GenerateRandomString(32)
	if err != nil {
		return nil, errors.New("生成验证令牌失败")
	}

	// 创建用户
	user := models.User{
		Username:                req.Username,
		Email:                   req.Email,
		Password:                hashedPassword,
		FirstName:               req.FirstName,
		LastName:                req.LastName,
		Phone:                   req.Phone,
		IsActive:                true,
		IsEmailVerified:         false,
		EmailVerificationToken:  emailToken,
		EmailVerificationExpiry: &[]time.Time{time.Now().Add(24 * time.Hour)}[0],
	}

	if err := database.DB.Create(&user).Error; err != nil {
		return nil, errors.New("创建用户失败")
	}

	// 分配默认角色（普通用户）
	var userRole models.Role
	if err := database.DB.Where("name = ?", "user").First(&userRole).Error; err == nil {
		userRoleAssignment := models.UserRole{
			UserID: user.ID,
			RoleID: userRole.ID,
		}
		database.DB.Create(&userRoleAssignment)
	}

	return &user, nil
}

// Login 用户登录
func (s *UserService) Login(req dto.LoginRequest) (*dto.AuthResponse, error) {
	var user models.User
	if err := database.DB.Preload("Roles.Permissions").Where("email = ?", req.Email).First(&user).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New("邮箱或密码错误")
		}
		return nil, errors.New("查询用户失败")
	}

	// 验证密码
	if err := utils.CheckPassword(user.Password, req.Password); err != nil {
		return nil, errors.New("邮箱或密码错误")
	}

	// 检查用户是否激活
	if !user.IsActive {
		return nil, errors.New("账户已被禁用")
	}

	// 生成访问令牌
	accessToken, err := utils.GenerateAccessToken(user.ID, user.Username, user.Email)
	if err != nil {
		return nil, errors.New("生成访问令牌失败")
	}

	// 生成刷新令牌
	refreshTokenString, err := utils.GenerateRefreshToken(user.ID, user.Username)
	if err != nil {
		return nil, errors.New("生成刷新令牌失败")
	}

	// 保存刷新令牌到数据库
	refreshToken := models.RefreshToken{
		UserID:    user.ID,
		Token:     refreshTokenString,
		ExpiresAt: time.Now().Add(30 * 24 * time.Hour), // 30天
	}
	if err := database.DB.Create(&refreshToken).Error; err != nil {
		return nil, errors.New("保存刷新令牌失败")
	}

	// 更新最后登录时间
	now := time.Now()
	user.LastLoginAt = &now
	database.DB.Save(&user)

	// 构建响应
	userInfo := s.BuildUserInfo(&user)
	
	return &dto.AuthResponse{
		AccessToken:  accessToken,
		RefreshToken: refreshTokenString,
		TokenType:    "Bearer",
		ExpiresIn:    24 * 3600, // 24小时，单位秒
		User:         userInfo,
	}, nil
}

// RefreshToken 刷新访问令牌
func (s *UserService) RefreshToken(req dto.RefreshTokenRequest) (*dto.AuthResponse, error) {
	// 验证刷新令牌
	var refreshToken models.RefreshToken
	if err := database.DB.Preload("User.Roles.Permissions").Where("token = ? AND is_revoked = false", req.RefreshToken).First(&refreshToken).Error; err != nil {
		return nil, errors.New("无效的刷新令牌")
	}

	// 检查令牌是否过期
	if refreshToken.IsExpired() {
		return nil, errors.New("刷新令牌已过期")
	}

	user := refreshToken.User

	// 生成新的访问令牌
	accessToken, err := utils.GenerateAccessToken(user.ID, user.Username, user.Email)
	if err != nil {
		return nil, errors.New("生成访问令牌失败")
	}

	// 生成新的刷新令牌
	newRefreshTokenString, err := utils.GenerateRefreshToken(user.ID, user.Username)
	if err != nil {
		return nil, errors.New("生成刷新令牌失败")
	}

	// 撤销旧的刷新令牌
	refreshToken.IsRevoked = true
	database.DB.Save(&refreshToken)

	// 保存新的刷新令牌
	newRefreshToken := models.RefreshToken{
		UserID:    user.ID,
		Token:     newRefreshTokenString,
		ExpiresAt: time.Now().Add(30 * 24 * time.Hour),
	}
	database.DB.Create(&newRefreshToken)

	// 构建响应
	userInfo := s.BuildUserInfo(&user)

	return &dto.AuthResponse{
		AccessToken:  accessToken,
		RefreshToken: newRefreshTokenString,
		TokenType:    "Bearer",
		ExpiresIn:    24 * 3600,
		User:         userInfo,
	}, nil
}

// GetUserByID 根据ID获取用户
func (s *UserService) GetUserByID(userID uint) (*models.User, error) {
	var user models.User
	if err := database.DB.Preload("Roles.Permissions").Where("id = ?", userID).First(&user).Error; err != nil {
		return nil, err
	}
	return &user, nil
}

// VerifyEmail 验证邮箱
func (s *UserService) VerifyEmail(token string) error {
	var user models.User
	if err := database.DB.Where("email_verification_token = ?", token).First(&user).Error; err != nil {
		return errors.New("无效的验证令牌")
	}

	// 检查令牌是否过期
	if user.EmailVerificationExpiry != nil && time.Now().After(*user.EmailVerificationExpiry) {
		return errors.New("验证令牌已过期")
	}

	// 更新用户状态
	now := time.Now()
	user.IsEmailVerified = true
	user.EmailVerifiedAt = &now
	user.EmailVerificationToken = ""
	user.EmailVerificationExpiry = nil

	return database.DB.Save(&user).Error
}

// ChangePassword 修改密码
func (s *UserService) ChangePassword(userID uint, req dto.ChangePasswordRequest) error {
	var user models.User
	if err := database.DB.Where("id = ?", userID).First(&user).Error; err != nil {
		return errors.New("用户不存在")
	}

	// 验证旧密码
	if err := utils.CheckPassword(user.Password, req.OldPassword); err != nil {
		return errors.New("旧密码错误")
	}

	// 加密新密码
	hashedPassword, err := utils.HashPassword(req.NewPassword)
	if err != nil {
		return errors.New("密码加密失败")
	}

	// 更新密码
	user.Password = hashedPassword
	return database.DB.Save(&user).Error
}

// BuildUserInfo 构建用户信息
func (s *UserService) BuildUserInfo(user *models.User) dto.UserInfo {
	roles := make([]dto.RoleInfo, len(user.Roles))
	for i, role := range user.Roles {
		permissions := make([]dto.PermissionInfo, len(role.Permissions))
		for j, permission := range role.Permissions {
			permissions[j] = dto.PermissionInfo{
				ID:          permission.ID,
				Name:        permission.Name,
				DisplayName: permission.DisplayName,
				Description: permission.Description,
				Resource:    permission.Resource,
				Action:      permission.Action,
			}
		}
		roles[i] = dto.RoleInfo{
			ID:          role.ID,
			Name:        role.Name,
			DisplayName: role.DisplayName,
			Description: role.Description,
			Permissions: permissions,
		}
	}

	return dto.UserInfo{
		ID:              user.ID,
		UUID:            user.UUID,
		Username:        user.Username,
		Email:           user.Email,
		FirstName:       user.FirstName,
		LastName:        user.LastName,
		Avatar:          user.Avatar,
		Phone:           user.Phone,
		IsActive:        user.IsActive,
		IsEmailVerified: user.IsEmailVerified,
		EmailVerifiedAt: user.EmailVerifiedAt,
		LastLoginAt:     user.LastLoginAt,
		CreatedAt:       user.CreatedAt,
		Roles:           roles,
	}
}